package org.pr.ddddesigner.infrastructure.support;

import ch.qos.logback.core.joran.node.ComponentNode;
import com.lion.commons.tools.component.AbstractFileResolver;
import com.lion.commons.tools.component.ComponentAnalyser;
import com.lion.commons.tools.component.SbmZipComponentAnalyser;
import com.lion.commons.tools.component.SbmzComponentAnalyser;
import com.lion.commons.tools.scene.Scene;
import com.xw.soonmanager.component.dto.BuildComponentRequestDto;
import com.xw.soonmanager.filemanager.ModelType;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import javax.xml.transform.Result;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;

import static com.xw.soonmanager.filemanager.ModelType.SBM;
import static com.xw.soonmanager.filemanager.ModelType.SBMZ;

/**
 * @author chenbin
 */
@Component
public class CompositeComponentBuilder implements ComponentBuilder {
    private static final Set<ModelType> SUPPORTED_TYPES = new HashSet<>(Arrays.asList(SBMZ, SBM));

    @Override
    public boolean support(ModelType type) {
        return false;
    }

    @Override
    public Mono<Result> build(BuildComponentRequestDto metadata) {
        return null;
    }

    /*private final FileManagerFacade2 fileManagerFacade;

    public CompositeComponentBuilder(FileManagerFacade2 fileManagerFacade) {
        this.fileManagerFacade = fileManagerFacade;
    }

    @Override
    public boolean support(ModelType type) {
        return SUPPORTED_TYPES.contains(type);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Mono<Result> build(BuildComponentRequestDto metadata) {
        ComponentAnalyser.FileResolver fileResolver = new AbstractFileResolver() {
            @Override
            public UUID getFileId() {
                return metadata.getFileId();
            }

            @Override
            public Mono<String> resolve(String entryName) {
                return fileManagerFacade.downloadFile(metadata.getFileId(), entryName)
                        .publishOn(Schedulers.boundedElastic())
                        .map(path -> {
                            try (InputStream in = Files.newInputStream(path)) {
                                return StreamUtils.copyToString(in, StandardCharsets.UTF_8);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        });
            }
        };

        return Mono.defer(() -> {
            ComponentAnalyser analyser;
            switch (metadata.getModelType()) {
                case SBMZ: {
                    analyser = new SbmzComponentAnalyser(metadata.getEntryList(), fileResolver);
                    break;
                }
                case SBM: {
                    analyser = new SbmZipComponentAnalyser(metadata.getEntryList(), fileResolver);
                    break;
                }
                default: {
                    return Mono.error(new IllegalArgumentException("不支持的类型"));
                }
            }
            return analyser.buildScene();
        }).flatMap(scene -> {
            Scene.Node root = scene.getRoot();
            if (root != null && !StringUtils.hasText(root.getName())) {
                root.setName(metadata.getName());
            }

            ModelComponent component = ComponentBuilder.createComponent(metadata);
            Mono<ModelComponent> componentMono = component.save();

            ComponentEdition edition = ComponentBuilder.createEdition(metadata);
            edition.setComponentId(component.getId());
            Mono<ComponentEdition> editionMono = edition.save();

            List<ComponentNode> nodes = ComponentBuilder.extractNodes(scene, () -> {
                ComponentNode node = ComponentBuilder.createNode(metadata);
                node.setComponentId(component.getId());
                node.setEditionId(edition.getId());
                return node;
            });
            Mono<Integer> nodesMono = ComponentNode.saveAll(nodes);

            Result result = new Result();
            result.setComponent(component);
            result.setEdition(edition);
            result.setNodes(nodes);

            return Mono.when(componentMono, editionMono, nodesMono).thenReturn(result);
        });
    }*/
}
